os.kill(pid, signal.SIGTERM)
xc.domain_stop( dom=dom )
- time.sleep(0.1);
+
+ while not xc.domain_getinfo( first_dom=dom, max_doms=1 )[0]['stopped']:
+ time.sleep(0.1);
+
rc = xc.linux_save( dom=dom, state_file=file, progress=1)
if rc == 0 : xc.domain_destroy( dom=dom, force=1 )
#include <asm-xen/suspend.h>
#include <zlib.h>
+#define BATCH_SIZE 512 /* 1024 pages (4MB) at a time */
+
/* This may allow us to create a 'quiet' command-line option, if necessary. */
#define verbose_printf(_f, _a...) \
do { \
_res; \
})
-static int check_pfn_ownership(int xc_handle,
- unsigned long mfn,
- u64 dom)
-{
- dom0_op_t op;
- op.cmd = DOM0_GETPAGEFRAMEINFO;
- op.u.getpageframeinfo.pfn = mfn;
- op.u.getpageframeinfo.domain = (domid_t)dom;
- return (do_dom0_op(xc_handle, &op) >= 0);
-}
-#define GETPFN_ERR (~0U)
-static unsigned int get_pfn_type(int xc_handle,
- unsigned long mfn,
- u64 dom)
-{
- dom0_op_t op;
- op.cmd = DOM0_GETPAGEFRAMEINFO;
- op.u.getpageframeinfo.pfn = mfn;
- op.u.getpageframeinfo.domain = (domid_t)dom;
- if ( do_dom0_op(xc_handle, &op) < 0 )
- {
- PERROR("Unexpected failure when getting page frame info!");
- return GETPFN_ERR;
- }
- return op.u.getpageframeinfo.type;
-}
static int checked_write(gzFile fd, void *buf, size_t count)
{
/*
- * Construct the local pfn-to-mfn and mfn-to-pfn tables. On exit from this
- * loop we have each MFN mapped at most once. Note that there may be MFNs
- * that aren't mapped at all: we detect these by MFN_IS_IN_PSEUDOPHYS_MAP.
+ * Quick sanity check.
*/
for ( i = 0; i < srec.nr_pfns; i++ )
{
mfn = live_pfn_to_mfn_table[i];
-#if 1 /* XXX use the master mfn_to_pfn table???? */
-
-
if( live_mfn_to_pfn_table[mfn] != i )
printf("i=%d mfn=%d live_mfn_to_pfn_table=%d\n",
i,mfn,live_mfn_to_pfn_table[mfn]);
+ }
- /* Query page type by MFN, but store it by PFN. */
- if ( (pfn_type[i] = get_pfn_type(xc_handle, mfn, domid)) ==
- GETPFN_ERR )
- goto out;
-#endif
+/* test new pfn_type stuff */
+ {
+ int n, i, j;
+
+ if ( mlock( pfn_type, srec.nr_pfns * sizeof(unsigned long) ) )
+ {
+ ERROR("Unable to mlock");
+ goto out;
+ }
+ for ( n = 0; n < srec.nr_pfns; )
+ {
+
+ for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
+ {
+ pfn_type[i] = live_pfn_to_mfn_table[i];
+ }
+
+ if ( get_pfn_type_batch(xc_handle, domid, j, &pfn_type[n]) )
+ {
+ ERROR("get_pfn_type_batch failed");
+ goto out;
+ }
+
+ for( j = 0, i = n; j < BATCH_SIZE && i < srec.nr_pfns ; j++, i++ )
+ {
+
+ pfn_type[i] >>= 29;
+
+ if(pfn_type[i] == 7)
+ {
+ ERROR("bogus page");
+ goto out;
+ }
+
+/* if(pfn_type[i])
+ printf("i=%d type=%d\n",i,pfn_type[i]); */
+ }
+
+ n+=j;
+ }
}
goto out;
}
- /* Belts and braces safety check on the shared info record */
- if ( !check_pfn_ownership(xc_handle, shared_info_frame, domid) )
- {
- ERROR("Invalid shared_info_frame");
- goto out;
- }
-
if ( !checked_write(gfd, "LinuxGuestRecord", 16) ||
!checked_write(gfd, name, sizeof(name)) ||
!checked_write(gfd, &srec.nr_pfns, sizeof(unsigned long)) ||
verbose_printf("Saving memory pages: 0%%");
-#define BATCH_SIZE 1024 /* 1024 pages (4MB) at a time */
-
if ( (mapper_handle2 = mfn_mapper_init(xc_handle, domid,
BATCH_SIZE*4096, PROT_READ ))
== NULL )
/*******************/
-typedef struct dom0_op_compact_getpageframeinfo {
- unsigned long cmd;
- unsigned long interface_version; /* DOM0_INTERFACE_VERSION */
- dom0_getpageframeinfo_t getpageframeinfo;
-} dom0_op_compact_getpageframeinfo_t;
-
-
-typedef struct mfn_typer {
- domid_t dom;
- int max;
- int nr_multicall_ents;
- multicall_entry_t *multicall_list;
- dom0_op_compact_getpageframeinfo_t *gpf_list;
-} mfn_typer_t;
-
-
-mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num );
-
-void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn );
-
-int mfn_typer_flush_queue(mfn_typer_t *t);
-
-unsigned int mfn_typer_get_result(mfn_typer_t *t, int idx);
+#if 0
mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num )
{
dom0_op_compact_getpageframeinfo_t *d;
t = calloc(1, sizeof(mfn_typer_t) );
- m = calloc(1, sizeof(multicall_entry_t)*num );
- d = calloc(1, sizeof(dom0_op_compact_getpageframeinfo_t)*num );
+ m = calloc(num, sizeof(multicall_entry_t));
+ d = calloc(num, sizeof(dom0_op_compact_getpageframeinfo_t));
if (!t || !m || !d)
{
return NULL;
}
+printf("sizeof(m)=%d sizeof(d)=%d m=%p d=%p\n",sizeof(multicall_entry_t), sizeof(dom0_op_compact_getpageframeinfo_t),m,d);
+
+ if ( (mlock(m, sizeof(multicall_entry_t)*num ) != 0) ||
+ (mlock(d, sizeof(dom0_op_compact_getpageframeinfo_t)*num ) != 0) )
+ {
+ PERROR("Could not lock memory for Xen hypercall");
+ return NULL;
+ }
+
+ t->xc_handle = xc_handle;
t->max = num;
t->nr_multicall_ents=0;
t->multicall_list=m;
d->interface_version = DOM0_INTERFACE_VERSION;
d->getpageframeinfo.pfn = mfn;
d->getpageframeinfo.domain = t->dom;
- d->getpageframeinfo.type = ~0UL;
+ d->getpageframeinfo.type = 1000; //~0UL;
m->op = __HYPERVISOR_dom0_op;
m->args[0] = (unsigned long)d;
int mfn_typer_flush_queue(mfn_typer_t *t)
{
if (t->nr_multicall_ents == 0) return 0;
- (void)HYPERVISOR_multicall(t->multicall_list, t->nr_multicall_ents);
+ do_multicall_op(t->xc_handle, t->multicall_list, t->nr_multicall_ents);
t->nr_multicall_ents = 0;
}
return t->gpf_list[idx].getpageframeinfo.type;
}
+#endif
+
+/* NB: arr must be mlock'ed */
+
+int get_pfn_type_batch(int xc_handle,
+ u64 dom, int num, unsigned long *arr)
+{
+ dom0_op_t op;
+ op.cmd = DOM0_GETPAGEFRAMEINFO2;
+ op.u.getpageframeinfo2.domain = (domid_t)dom;
+ op.u.getpageframeinfo2.num = num;
+ op.u.getpageframeinfo2.array = arr;
+ return do_dom0_op(xc_handle, &op);
+}
+
+#define GETPFN_ERR (~0U)
+unsigned int get_pfn_type(int xc_handle,
+ unsigned long mfn,
+ u64 dom)
+{
+ dom0_op_t op;
+ op.cmd = DOM0_GETPAGEFRAMEINFO;
+ op.u.getpageframeinfo.pfn = mfn;
+ op.u.getpageframeinfo.domain = (domid_t)dom;
+ if ( do_dom0_op(xc_handle, &op) < 0 )
+ {
+ PERROR("Unexpected failure when getting page frame info!");
+ return GETPFN_ERR;
+ }
+ return op.u.getpageframeinfo.type;
+}
+
/*******************/
out1: return ret;
}
+static inline int do_multicall_op(int xc_handle,
+ void *call_list, int nr_calls)
+{
+ int ret = -1;
+ privcmd_hypercall_t hypercall;
+
+ hypercall.op = __HYPERVISOR_multicall;
+ hypercall.arg[0] = (unsigned long)call_list;
+ hypercall.arg[1] = (unsigned long)nr_calls;
+
+ if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
+ {
+ if ( errno == EACCES )
+ fprintf(stderr, "Dom0 operation failed -- need to"
+ " rebuild the user-space tool set?\n");
+ goto out1;
+ }
+
+ out1: return ret;
+}
+
static inline int do_network_op(int xc_handle, network_op_t *op)
{
int ret = -1;
void * mfn_mapper_queue_entry(mfn_mapper_t *t, int offset,
unsigned long mfn, int size );
+/*********************/
+
+
+#if 0
+typedef struct mfn_typer {
+ domid_t dom;
+ int xc_handle;
+ int max;
+ dom0_op_t op;
+} mfn_typer_t;
+
+
+mfn_typer_t *mfn_typer_init(int xc_handle, domid_t dom, int num );
+
+void mfn_typer_queue_entry(mfn_typer_t *t, unsigned long mfn );
+
+int mfn_typer_flush_queue(mfn_typer_t *t);
+#endif
+
+int get_pfn_type_batch(int xc_handle,
+ u64 dom, int num, unsigned long *arr);
+
+unsigned int get_pfn_type(int xc_handle,
+ unsigned long mfn,
+ u64 dom);
+
#endif /* __XC_PRIVATE_H__ */
}
break;
+ case DOM0_GETPAGEFRAMEINFO2:
+ {
+#define GPF2_BATCH 128
+ int n,j;
+ int num = op->u.getpageframeinfo2.num;
+ domid_t dom = op->u.getpageframeinfo2.domain;
+ unsigned long *s_ptr = (unsigned long*) op->u.getpageframeinfo2.array;
+ struct task_struct *p;
+ unsigned long l_arr[GPF2_BATCH];
+ ret = -ESRCH;
+
+ if ( unlikely((p = find_domain_by_id(dom)) == NULL) )
+ break;
+
+ if ( unlikely(num>1024) )
+ {
+ ret = -E2BIG;
+ break;
+ }
+
+ ret = 0;
+ for(n=0;n<num;)
+ {
+ int k = ((num-n)>GPF2_BATCH)?GPF2_BATCH:(num-n);
+
+ if( copy_from_user( l_arr, &s_ptr[n], k*sizeof(unsigned long) ) )
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ for(j=0;j<k;j++)
+ {
+ struct pfn_info *page;
+ unsigned long mfn = l_arr[j];
+
+ if ( unlikely(mfn >= max_page) )
+ goto e2_err;
+
+ page = &frame_table[mfn];
+
+ if ( likely(get_page(page, p)) )
+ {
+ unsigned long type = 0;
+ switch( page->type_and_flags & PGT_type_mask )
+ {
+ case PGT_l1_page_table:
+ case PGT_l2_page_table:
+ case PGT_l3_page_table:
+ case PGT_l4_page_table:
+ type = page->type_and_flags & PGT_type_mask;
+
+ }
+ l_arr[j] |= type;
+ put_page(page);
+ }
+ else
+ {
+ e2_err:
+ l_arr[j] |= PGT_type_mask; /* error */
+ }
+
+ }
+
+ if( copy_to_user( &s_ptr[n], l_arr, k*sizeof(unsigned long) ) )
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ n+=j;
+ }
+
+ put_task_struct(p);
+
+ }
+ break;
+
default:
ret = -ENOSYS;
unsigned int max_memkb;
} dom0_setdomainmaxmem_t;
+#define DOM0_GETPAGEFRAMEINFO2 29 /* batched interface */
+typedef struct dom0_getpageframeinfo2_st
+{
+ /* IN variables. */
+ domid_t domain; /* To which domain do frames belong? */
+ int num;
+ /* IN/OUT variables. */
+ unsigned long *array;
+} dom0_getpageframeinfo2_t;
+
typedef struct dom0_op_st
{
dom0_setdomainname_t setdomainname;
dom0_setdomaininitialmem_t setdomaininitialmem;
dom0_setdomainmaxmem_t setdomainmaxmem;
+ dom0_getpageframeinfo2_t getpageframeinfo2;
} u;
} dom0_op_t;